package com.wq.payunion.oauth2.useroauth2.oauth2;

import com.wq.payunion.oauth2.useroauth2.exceptions.OAuthException;
import com.wq.payunion.oauth2.useroauth2.model.AbstractOAuthBean;
import com.wq.payunion.oauth2.useroauth2.model.AccessTokenParam;
import com.wq.payunion.oauth2.useroauth2.model.OAuthInfoParam;
import com.wq.payunion.oauth2.useroauth2.model.OAuthResult;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: wangqiang20995
 * @Date:2018 年 9 月 15 日 0015
 * @Description:
 * @Resource:
 */
@Service
public class OAuthTemplate {

    private ThirdSystemOAuth thirdSystemOAuth;//此时不再是线程安全的，采用策略模式，通过set可以随时变换

    private Map<String,AbstractOAuthBean> authorizeRelations;

    private ThreadLocal<ThirdSystemOAuth> oAuthThreadLocal;


    public ThirdSystemOAuth getThirdSystemOAuth() {
        return thirdSystemOAuth;
    }

    public void setThirdSystemOAuth(ThirdSystemOAuth thirdSystemOAuth) {
        this.thirdSystemOAuth = thirdSystemOAuth;
        this.oAuthThreadLocal.set(thirdSystemOAuth);
    }

    public OAuthTemplate(){
        authorizeRelations = new ConcurrentHashMap<>();
        this.oAuthThreadLocal = new ThreadLocal<>();
    }

    public OAuthResult executeAuthorize(AbstractOAuthBean oAuthBean,String extract){
        String uuid = oAuthBean.getUuid();
        OAuthResult oAuthResult = new OAuthResult();
        if(this.oAuthThreadLocal.get().equals(thirdSystemOAuth)) {
            ThirdSystemOAuth systemOAuth = this.oAuthThreadLocal.get();
            if (StringUtils.isEmpty(uuid)) {//code

                if(StringUtils.isEmpty(extract) && oAuthBean instanceof OAuthInfoParam){
                    Map<String,Object> returnMap = systemOAuth.oauthWithAccessToken((OAuthInfoParam) oAuthBean);
                    oAuthResult= doAuthorizeInfoByToken(returnMap);
                }else {
                    oAuthResult = systemOAuth.generatorRedirectUrl(oAuthBean, extract);
                    this.authorizeRelations.put(oAuthResult.getUuid(), oAuthBean);//暂且存下来，下一步accesstoken要需要验证uuid的有效性
                }

            } else {//accessToken
                oAuthResult = doOAuthResult(oAuthBean, extract);
                this.authorizeRelations.remove(uuid);//删除记录，代表code-->accessToken完成
            }

        }else {
            throw new OAuthException("9999","并发问题，系统异常");
        }

        return oAuthResult;
    }

    private OAuthResult doAuthorizeInfoByToken(Map<String,Object> returnJson){
        OAuthResult oAuthResult = new OAuthResult();
        oAuthResult.setAuthStatus(OAuthResult.AuthStatus.AUTHORIZATION_EXTRACT_INFO);
        if(returnJson.size() == 0){
            oAuthResult.setSuccessFlag(false);
            oAuthResult.setCallInfo("用token获取授权信息接口返回内容为空");
        }else {
            oAuthResult.setSuccessFlag(true);
            oAuthResult.setCallInfo("用token获取授权接口信息成功");
            oAuthResult.setResponse(returnJson);
        }

        return oAuthResult;
    }
    private OAuthResult doOAuthResult(AbstractOAuthBean oAuthBean, String extract) {
        OAuthResult oAuthResult = new OAuthResult();
        String uuid = oAuthBean.getUuid();
        if (this.authorizeRelations.containsKey(uuid)) {//暂时先设置为一次请求的有消息，之后可以将accesstoken落库
            //accessToken
            AccessTokenParam accessTokenParam = new AccessTokenParam();
            accessTokenParam.setUuid(oAuthBean.getUuid());
            accessTokenParam.setOauthName(oAuthBean.getOauthName());
            Map<String,Object> result = this.thirdSystemOAuth.accessToken(accessTokenParam,extract);

            oAuthResult.setUuid(uuid);
            oAuthResult.setAuthStatus(OAuthResult.AuthStatus.AUTHORIZATION_ACCESS_TOKEN);
            oAuthResult.setSuccessFlag(result.containsKey("access_token"));
            oAuthResult.setCallInfo("获取accessToken接口调用成功");
            oAuthResult.setResponse(result);

            return oAuthResult;
        } else {
            oAuthResult.setSuccessFlag(false);
            oAuthResult.setCallInfo("通过code获取accesstoken的标识符违法");
            return oAuthResult;
        }
    }

    public OAuthResult executeAuthorize(String oauth,String extract){
        return this.executeAuthorize(new AbstractOAuthBean(oauth),extract);
    }
}
